package kernel;

import java.util.Scanner;

import adt.CalcProcess;
import adt.ConsumerProcess;
import adt.ProducerProcess;
import adt.UIProcess;

/**
 * 
 * @author Aaron Fung
 *		   Chris Ren
 * @version 1.0	
 */
public class SimulatorMain {

	private static CPU my_cpu = new CPU();
	private static int pid = 1;
	/**
	 * Main class for the Scheduler Simulator.
	 * 
	 * @param args arguments for the main.
	 */
	public static void main(final String[] args) {
		//int num_process = Integer.parseInt(args[0]);
		
		// Displays an introductory to the Scheduling Simulator.
		displayIntroduction();
		//Displays and handles menu choices.
		displayMenu();
	}
	
	/**
	 * Displays a simple introduction about the purpose of
	 * the application.
	 */
	private static void displayIntroduction() {
		System.out.print("Welcome to the Scheduling Simulation Program!");
		System.out.print("\nThis program will simulate how a CPU handles "
				+ "\nscheduling based on timer interrupts, i/o request, many more!\n");
	}
	
	/**
	 * 
	 * @param the_console Scanner to be used for getting the user's input.
	 * @param the_cpu
	 */
	private static void displayMenu() {
		final Scanner console = new Scanner(System.in);
		int num_process = 0;
		
		// Retrieve which process they want and how many of that process.
	    System.out.print("\nPlease select a process and the amount you want to run.");
	    System.out.print("\n(Note: The order you select determines the order they are ran):");
	    System.out.print("\n\t1. UI Process");
	    System.out.print("\n\t2. Background Process");
	    System.out.print("\n\t3. Consumer-Producer Processs");
	    System.out.print("\n\t4. Start Application");
	    System.out.print("\n\t0. Exit");
	    
		switch (getUserChoice(console, 0, 4, "Please enter a menu number: ")) {
		case 1:
			num_process = getNumProcess(console);
			for (int i = 0; i < num_process; i++) {
				my_cpu.process_ready(new UIProcess(pid));
				pid++;
			}
			displayMenu();
			break;
		case 2:
			num_process = getNumProcess(console);
			for (int i = 0; i < num_process; i++) {
				my_cpu.process_ready(new CalcProcess(pid));
				pid++;
			}
			displayMenu();
			break;
		case 3:
			num_process = getNumProcess(console);
			for (int i = 0; i < num_process; i++) {
				my_cpu.process_ready(new ConsumerProcess(pid));
				pid++;
				my_cpu.process_ready(new ProducerProcess(pid));
				pid++;
			}
			displayMenu();
			break;
		case 4:
			//Starts the actual application that will simulate
			//a CPU's scheduling.
			System.out.print("\nBeginning Simulation......\n\n");
			my_cpu.start();
			break;
		default: // includes choice of 0
			System.out
					.print("\n\nThanks for using our Sceduling Simulator application!");
			return; // Exits program.
		}
	}
	
	/**
	 * 
	 * @param the_console Scanner to be used for getting the user's input.
	 * @return the number of processes the user has inputed.
	 */
	private static int getNumProcess(final Scanner the_console) {
		
		int num_process = 0;
		while(true) {
			System.out.print("\nPlease enter the number of process: ");
			num_process = the_console.nextInt();
			if (num_process < 1) {
				System.out.print("\nNumber of process must be greater than 0.");
			} else {
				break;
			}
		}
		return num_process;
	}
	
	/**
	 * Gets an integer value from the user between the_min and the_max.
	 * 
	 * @param the_console
	 *            Scanner to be used for getting the user's input.
	 * @param the_min
	 *            int representing the first menu choice.
	 * @param the_max
	 *            int representing the last menu choice.
	 * @param the_message
	 *            String containing the message for asking the user for input,
	 *            is automatically preceded with a new line character.
	 * @return int containing the user's menu choice.
	 */
	private static int getUserChoice(final Scanner the_console,
			final int the_min, final int the_max, final String the_message) {
		int user_choice = the_min - 1;

		while (user_choice < the_min || user_choice > the_max) {
			System.out.print("\n" + the_message);
			user_choice = the_console.nextInt();
			the_console.nextLine();

			if (user_choice < the_min || user_choice > the_max) {
				System.out.print("\nError: entry out of bounds");
			}
		}
		return user_choice;
	}
}
